#ifndef OBJECT_H_
#define OBJECT_H_

#include <time.h>
#include "Vector2D.h"
#include "Vector2DList.h"
#include "Force.h"
#include "Material.h"
#include "TextureManager.h"
#include "LineSegment.h"
#include "Sprite.h"
#include "Dictionary.h"
#include "FrictionInfoList.h"

class Object
{

	protected:
	Vector2D * textureVertices;
	FrictionInfoList * frictionInfoList;
	bool letMeGo;
	bool collideWithGround;
	
	public:
	TextureManager * textureManager;
	Object * objectToCreate;
	Object * objectToDestroy;
	float mass;
	
	float angularMass;
	float rotation;
	float angularAcceleration;
	float angularVelocity;
	
	double lastElapsedTime;
	Vector2D translationalForce;
	float torque;
	Material * material;
	
	Vector2D collisionLocations[5];
	
	int objectId;
	bool collideWhenGrabbed;
	bool collisionValid;
	Vector2D collisionPoint;
	Vector2D position;
	Vector2D velocity;
	Vector2D acceleration;
	bool isPinned;
	bool cantShift;
	Vector2D * vertices;
	Vector2D upVector;
	Vector2D collisionEdge[2];
	int numVertices;
	int onGroundFilter;
	bool hitGround;
	float boundingRadius;
	bool isOnGround;
	bool isColliding;
	bool isOnRightWall;
	bool isOnLeftWall;
	virtual void CalculateUpVector();
	virtual void CalculateMomentOfInertia();
	virtual void Rotate(float theta);
	virtual bool PreRotate(float theta);
	virtual void Rotate(Vector2D radius, Vector2D delta);
	int IsVertex(Vector2D point);
	void ProjectPolygon(Vector2D axis, float * min, float * max, Vector2D * minVertex, Vector2D * maxVertex, float * minError, float * maxError);
	virtual Vector2D VelocityAtPoint(Vector2D point);
	void CalculateTextureVertices(float theta);
public:
	
	Vector2DList * keyPointList;
	void AddKeyPoint(Vector2D * point);
	void RemoveKeyPoint(Vector2D point);
	void RemoveKeyPoint(Vector2D * point);
	virtual void ReleasingObject();
	virtual void PickingUpObject();
	int numCollisions;
	Object();
	Object( TextureManager * textureManager,
			Vector2D position,
			Vector2D * vertices,
			int numVertices,
			float mass,
			bool isGrabbable);
	Object( TextureManager * textureManager,
			Material * material,
			float textureRotation,
			Vector2D position, 
			Vector2D velocity,
			Vector2D acceleration,
			Vector2D * vertices,
			int numVertices,
			float rotation,
			float angularVelocity,
			float angularAcceleration,
			float mass,
			bool isPinned);
	Object(  TextureManager * textureManager,
			Material * material,
			float textureRotation,
			Vector2D position, 
			Vector2D velocity,
			Vector2D acceleration,
			Vector2D * vertices,
			int numVertices,
			float rotation,
			float angularVelocity,
			float angularAcceleration,
			float mass,
			bool isPinned,
			bool collideWhenGrabbed);
	virtual ~Object();
	virtual void AddForce(Vector2D ray);
	virtual void AddForce(Force force);
	virtual void AddForce(Vector2D ray, Vector2D origin);
	virtual void AddForceObjectSpace(Vector2D ray, Vector2D origin);
	virtual void AddForceObjectSpace(Vector2D ray, Vector2D origin, bool groundForce);
	virtual void AddContactPointObjectSpace(Vector2D normalForce, Vector2D contactPoint, LineSegment lineSegment);
	virtual void AddContactPointObjectSpace(Vector2D normalForce, Vector2D contactPoint, LineSegment lineSegment, Vector2D velocity);
	virtual void AddGravity();
	virtual void AddFriction(double elapsedTime);
	virtual bool PreThinkEntryPoint(double elapsedTime);
	virtual void ThinkEntryPoint(double elapsedTime);
	
	virtual void Draw();
	virtual void DrawCollision();
	virtual void DrawEntryPoint();
	virtual bool PreDrawEntryPoint();
	virtual void Think(double elapsedTime);
	virtual bool CanCollideWith(Object * object);
	virtual bool CollideSprite(Sprite * sprite);
	virtual bool Collide(Object * object2, double elapsedTime);
	virtual bool Collide(Object * object1, Object * object2, double elapsedTime);
	virtual bool Collide2(Object * object1, Object * object2, double elapsedTime);
	virtual void CollidedWith(Object * object2, float power, Vector2D finalVertex2);
	bool CollideWithSegment(Object * object1, Object * object2, float * minDistance, float * minError, Vector2D * finalResult, Vector2D * finalOrigin);
	bool LetMeGo();
	virtual Object * CreateObject();
	virtual Object * DestroyObject();
	virtual void AddDamage(float damage);
	virtual char * Action(Vector2D playerPos, Dictionary * gameState);
	bool GetCollideWithGround() const;
};
float IntervalDistance( Vector2D point1, Vector2D point2, Vector2D minVertex, Vector2D maxVertex, float minError, float maxError, Vector2D * finalVertex, float * finalError);
float abs(float num); 
#endif /*OBJECT_H_*/

